iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0
生成式 AI

生成式AI 與 Notion 的碰撞 ?! 你還在 ctrl+c ctrl+v ?系列 第 30

Day 30 | Google Calendar 同步 Notion 單向 CU 無法擁有的Notion Delete

  • 分享至 

  • xImage
  •  

今天進度

今天的工作流會跟作天的 Notion 同步 Google Calendar 完成版很像,但會有一些邏輯不一樣。

像是要修改AI Agent 的prompt、邏輯處理的部分。

今天我們將會理用兩個單向的同步工具去達到最終的,雙向同步,但在開始之前必須跟讀者說明,在今天的實作無法做到 Google Calendar 事件取消同步至Notion 我們退而求其次修改Notion的狀態設定為乙取消 。


流程介紹

整個流程可以分為三個部分:

  1. 建立活動流程:
    • 觸發 (Trigger): 流程由「GCal Create Trigger」開始。當 Google 日曆上建立一個新活動 (eventCreated) 時,這個流程就會被觸發。
    • AI 處理 (AI Agent): 觸發後,會將活動資訊傳送給一個名為「AI Agent Prompt for Create」的 AI 代理。
      • 這個 AI 代理會使用「Google Gemini Create」模型和一個名為「Create Tool for Create」的工具。
      • 它的任務是理解日曆活動的內容,並將其轉換成結構化的資料。
    • 更新資料庫 (Database): 經過「Structured Output Parser3」解析後的結構化資料,會被送到 Notion 的「Update a database page」模組,在資料庫中新增一筆對應的頁面。
    • 發送通知 (Notification): 最後,透過「LINE Bot 通知」模組,發送一個 POST 請求到指定的網址,通知使用者有新的日曆活動已建立。
  2. 更新活動流程:
    • 觸發 (Trigger): 當 Google 日曆上的某個活動被更新 (eventUpdated) 時,「GCal Update Trigger」會啟動這個流程。
    • AI 處理 (AI Agent): 活動的更新資訊會被傳送到「AI Agent Prompt for UPDATE」。
      • 這個 AI 代理使用了更複雜的工具組合,包括「Google Gemini for Update」模型、「Update Tool for Update」和「Search Tool for Updata」。這表示它不僅能理解更新內容,還能搜尋資料庫中既有的活動資訊。
    • 更新資料庫 (Database): 處理完畢的資料,會透過「Structured Output Parser」傳遞給 Notion 的「Update a database page」模組,以更新資料庫中對應的頁面內容。
    • 發送通知 (Notification): 最後,流程會透過「LINE Bot 通知Updata」模組,發送 LINE 通知,告知使用者某個活動已被更新。
  3. 刪除活動流程 :
    • 觸發 (Trigger): 當 Google 日曆上的活動被取消或刪除 (eventCancelled) 時,「GCal Delete Trigger」會啟動此流程。
    • AI 處理 (AI Agent): 相關資訊會傳送到「AI Agent Prompt for...」(推測為 for Delete)。
      • 這個 AI 代理同樣使用了多個工具,包括「Google Gemini forUpdate Delete」、「Search Tool for Delete」和「Update Tool for Delete」,用來在資料庫中找到並處理要刪除的項目。
    • 更新資料庫 (Database): 結構化後的指令會送到 Notion 的「Update a Last Edited」模組,可能是用來標記或封存該頁面,而非直接刪除。
    • 發送通知 (Notification): 最終,透過「LINE Bot Delete 通知」模組,發送 LINE 通知,告知使用者某個日曆活動已被刪除。

這次我們是分成三個分別的工作流,而不是使用AI Agent判斷是哪個trigger被觸發,這樣我們確保了流程的穩定度跟更好的除錯。
image

實作流程

在 Notion 新增一個 Last Edited By 屬性,並在上一個流程最後一個 Updata Notion 修改為notion讓我們的流程不要進入一個無窮迴圈,若沒有這個機制會變這樣:Notion 更新 → 觸發流程 → 更新 Google 日曆 → 觸發另一個流程 → 更新 Notion → 再次觸發第一個流程 ... 如此循環。

所以這步驟是必須的。

建立活動流程

節點設定:GCal Create Trigger (Google Calendar Trigger)

  • 功能:這是整個流程的起點。它會定期檢查指定的 Google 日曆,一旦有新的活動被建立,它就會被觸發並啟動整個工作流程。
  • 如何設定
    1. 在 n8n 畫布上,新增一個 Google Calendar Trigger 節點。
    2. Credentials: 點擊 Credential to connect with,選擇或建立 Google Calendar OAuth2 憑證,並授權 n8n 存取。
    3. Calendar: 在 Calendar ID 欄位,選擇想要監控的那個日曆。
    4. Trigger On: 將這個選項設定為 Event Created (活動建立時觸發)。
    5. Polling: 在 Poll Times 設定檢查頻率,例如設定為 Every Minute (每分鐘檢查一次)。

我們需要一個自動化的起點,而不是手動執行。透過監控日曆的Created 事件,可以確保每個新活動都能即時被處理,實現完全自動化。

節點設定:AI Agent Prompt for Create (LangChain Agent)

AI Agent:

  • 功能:這是流程的「大腦」。它接收來自 Google 日曆的資料,並根據給定的指令(Prompt),驅動語言模型(Gemini)去思考,並決定要使用哪個工具(Notion)來完成任務。
  • 如何設定
    1. 新增一個 AI Agent 節點。

    2. 將 GCal Create Trigger 節點的輸出端連接到此節點的輸入端。

    3. Prompt: 在 Text 欄位中,貼上以下這段指令。這段指令非常關鍵,它告訴 AI 它的角色、任務、以及如何將 Google 日曆的欄位對應到 Notion 資料庫的欄位。codeText

      # Notion 頁面創建助理
      
      你是專責處理「新建立 Google Calendar 事件」並將其同步到 Notion 的 AI 助理。
      
      ## 核心任務
      你的唯一任務是呼叫 `Create Tool for Create` 工具,並根據下方規則精確填寫參數。
      
      ## 欄位映射規則
      - 活動名稱 (Name): 來自 Google Calendar 事件的 `summary`。
      - 目標完成時間 (Date Property): 
        - `start`: 來自 `start.dateTime`。若該值不存在,則使用 `start.date`。
        - `end`: 來自 `end.dateTime`。若該值不存在,則使用 `end.date`。
      - GCal_Event_ID (Text Property): 必須填入來自 Google Calendar 事件的 `id`,這是建立關聯的關鍵。
      - Last Edited By (Text Property): 將此欄位的值固定設為「Google Calendar」。
      - 狀態 (Status Property): 將此欄位的值固定設為「待處理」。
      - 重要程度 (Select Property): 預設為空,不填寫。
      - 緊不緊急 (Select Property): 預設為空,不填寫。
      
      ## 輸入的事件資料
      {{ JSON.stringify($json) }}
      
      ## 執行指示
      請立即根據上述規則,呼叫 `create_database_page_in_Notion` 工具來創建頁面。
      
    4. 勾選 Has Output Parser 選項。

我們不只是簡單地把資料從 A 搬到 B。我們利用 AI Agent 來進行邏輯處理,例如判斷日期格式、設定固定值(如「狀態」欄位),這讓流程更加靈活和智慧。{{ JSON.stringify($json) }} 這行程式碼會將上一個節點(日曆觸發器)傳來的完整資料餵給 AI。

Create Tool for Create:

  • 功能:這是一個被 AI Agent 用來在 Notion 中「建立頁面」的工具。
  • 如何設定
    1. 新增一個 Notion 節點,並在節點設定中將 Execution Mode 設為 Tool。
    2. Credentials: 連結您的 Notion 帳號。
    3. Resource: 選擇 Database/Page。
    4. Database ID: 選擇您要同步的 Notion 資料庫。
    5. 將這個節點的輸出端(菱形圖示)連接到 AI Agent Prompt for Create 節點的 Tool 輸入端。

Structured Output Parser:

  • 功能:這組節點的目的是「規範 AI 的輸出格式」。AI Agent 在執行完工具後,會產生一個結果。我們透過這組 Parser(解析器)來確保結果永遠是我們想要的 JSON 格式,方便後續節點使用。
  • 如何設定
    1. 新增一個 Structured Output Parser 節點。

    2. 在 JSON Schema Example 欄位中,貼上以下結構,定義你希望 AI 最終輸出的格式:

      {
        "type": "object",
        "properties": {
          "tool_result": {
            "type": "object",
            "GCal_Event_ID": "object",
            "Notion_Event_ID": "object",
            "description": "The raw, unmodified result from the executed tool。"
          }
        }
      }
      
    3. 新增另一個 Google Gemini Chat Model 節點 (Model3),並連結您的 API 金鑰。

    4. 連接

      • 將 Model3 的輸出連接到 Structured Output Parser3 的 Language Model 輸入。
      • 將 Structured Output Parser3 的輸出連接到 AI Agent Prompt for Create 節點的 Output Parser 輸入。

節點設定:Update a database page (Notion Node)

  • 功能:這個節點執行一個關鍵的「回寫」操作。AI Agent 建立 Notion 頁面後,會得到一個新的 Notion 頁面 ID。這個節點的任務是,將這個新頁面的 GCal_Event_ID 欄位更新為原始的 Google 日曆活動 ID。
  • 如何設定
    1. 新增一個普通的 Notion 節點 (不是 Tool 模式)。
    2. 將 AI Agent Prompt for Create 的輸出連接到此節點的輸入。
    3. Credentials: 連結您的 Notion 帳號。
    4. Resource: 選擇 Database/Page。
    5. Operation: 選擇 Update。
    6. Page ID: 點擊旁邊的齒輪,選擇 Add Expression,並填入 {{ $json.output.properties.tool_result.Notion_Event_ID }}。這會從 AI 的輸出中動態獲取剛剛建立的 Notion 頁面 ID。
    7. Properties:
      • 點擊 Add Property,選擇 GCal_Event_ID 欄位。
      • 在輸入框中,使用表達式填入 {{ $json.output.properties.tool_result.GCal_Event_ID }}。

這一步驟建立了 Google 日曆和 Notion 之間的唯一關聯。當未來需要「更新」或「刪除」活動時,我們才能憑藉這個儲存好的 GCal_Event_ID 在 Notion 資料庫中找到對應的那一筆資料。

節點設定:LINE Bot 通知 (HTTP Request)

  • 功能:作為流程的最後一步,向您的 LINE 發送一條通知,告知任務已完成。
  • 如何設定
    1. 新增一個 HTTP Request 節點。

    2. 將 Update a database page 的輸出連接到此節點的輸入。

    3. Method: 選擇 POST。

    4. URL: 填入 LINE 的廣播 API 網址。

    5. Headers:

      • 新增一個名為 Authorization 的 Header,值為 Bearer YOUR_LINE_CHANNEL_ACCESS_TOKEN (請換成您自己的 Token)。
      • 新增一個名為 Content-Type 的 Header,值為 application/json。
    6. Body: 選擇 JSON,並貼上以下內容:

      {
        "messages": [
          {
            "type": "text",
            "text": "{{$node["AI Agent Prompt for Create"].json.output.properties.tool_result.description}}"
          }
        ]
      }
      

這提供了即時的回饋,讓您知道自動化流程是否成功執行。訊息內容直接取自 AI Agent 處理後的描述,非常智慧化。

完成以上所有設定並正確連接節點後,建立活動流程會像這樣:
image

更新活動流程

這個流程的目標是:當 Google 日曆中的某個活動被修改時,自動在 Notion 中找到對應的頁面,並同步更新其內容。

節點設定:GCal Update Trigger (Google Calendar Trigger)

  • 功能:與建立流程相似,這是更新流程的起點。它會監控指定的 Google 日曆,一旦有活動被更新,就會觸發。
  • 如何設定
    1. 這部分的設定與「建立活動流程設定指引」中的 GCal Create Trigger 幾乎完全相同。
    2. 唯一的關鍵差別是,在 Trigger On 這個選項,您必須將其設定為 Event Updated (活動更新時觸發)。
  • 為何這樣設定:我們需要針對不同的事件(建立、更新、刪除)有不同的處理流程。將觸發條件設為 Event Updated 可以確保只有在日曆活動被修改時,這個流程才會啟動,避免與建立流程互相干擾。

節點設定:AI Agent Prompt for UPDATE (LangChain Agent)

  • 功能:同樣地,這是更新流程的「大腦」。但這次它的任務更複雜:它不僅要理解更新了什麼,還必須先使用「搜尋工具」在 Notion 中找到正確的頁面,然後再用「更新工具」去修改它。
  • 如何設定
    1. 新增一個 LangChain Agent 節點,並將 GCal Update Trigger 連接到它的輸入端。

    2. Prompt: 在 Text 欄位中,貼上針對「更新」設計的指令。這段指令會引導 AI 執行「先搜尋、後更新」的兩步驟任務。

      # Notion 頁面更新助理
      
      你是專責處理「已更新的 Google Calendar 事件」並將其同步到 Notion 的 AI 助理。
      
      ## 核心任務
      你的任務分為兩步:
      1.  **搜尋**: 使用 `Search Tool for Updata` 工具,根據輸入資料中的 `id` (GCal_Event_ID),在 Notion 資料庫中找到對應的頁面。
      2.  **更新**: 找到頁面後,呼叫 `Update Tool for Upata` 工具,並根據下方規則更新該頁面的欄位。
      
      ## 欄位映射規則 (更新)
      - **活動名稱 (Name)**: 更新為來自 Google Calendar 事件的 `summary`。
      - **目標完成時間 (Date Property)**: 
        - `start`: 更新為 `start.dateTime` 或 `start.date`。
        - `end`: 更新為 `end.dateTime` 或 `end.date`。
      - **Last Edited By (Text Property)**: 將此欄位的值更新為「Google Calendar」。
      - **其他欄位**: 除非有明確指示,否則保持不變。
      
      ## 輸入的更新事件資料
      {{ JSON.stringify($json) }}
      
      ## 執行指示
      請立即根據上述任務,先搜尋,再更新 Notion 頁面。
      
    3. 與建立流程一樣,您需要為這個 Agent 連接 語言模型 (Language Model)工具 (Tools) 和 輸出解析器 (Output Parser)

  • 為何這樣設定:更新操作的容錯率較低,必須確保修改的是正確的資料。因此,Prompt 中明確指示 AI 要先用 GCal_Event_ID 作為唯一標識進行搜尋,這正是我們在「建立流程」的 Update a database page 節點中 painstakingly 回寫 ID 的原因。

AI Agent 的工具箱 (Tools)

對於更新流程,AI Agent 需要兩個工具:一個用來找,一個用來改。

1. Search Tool for Updata (Notion Tool)

  • 功能:這是一個被 AI Agent 用來在 Notion 中「搜尋頁面」的工具。
  • 如何設定
    1. 新增一個 Notion 節點,並將 Execution Mode 設為 Tool
    2. Credentials: 連結您的 Notion 帳號。
    3. Resource: 選擇 Database/Page
    4. Operation: 選擇 Search
    5. 將這個節點的輸出端(菱形圖示)連接到 AI Agent Prompt for UPDATE 節點的 Tool 輸入端。

2. Update Tool for Upata (Notion Tool)

  • 功能:這是一個被 AI Agent 用來「更新特定頁面」的工具。
  • 如何設定
    1. 再新增一個 Notion 節點,同樣將 Execution Mode 設為 Tool
    2. Credentials: 連結您的 Notion 帳號。
    3. Resource: 選擇 Database/Page
    4. Operation: 選擇 Update
    5. 將這個節點的輸出端(菱形圖示)也連接到 AI Agent Prompt for UPDATE 節點的 Tool 輸入端。
  • 為何這樣設定:我們為 AI 提供了更豐富的工具箱。Agent 會根據 Prompt 的指令(先搜尋,後更新),智能地選擇要先使用 Search Tool 還是 Update Tool,並能將 Search Tool 找到的 Page ID 傳遞給 Update Tool 使用,完成複雜的任務。
    image

節點設定:Structured Output Parser & LINE Bot 通知

這兩個部分的概念與「建立活動流程設定指引」完全相同。

  • Structured Output Parser
    • 功能與設定:完全比照建立流程的設定。它的目的依然是規範 AI 的輸出格式,確保無論 AI 執行了搜尋還是更新,最終都能回傳一個結構穩定、方便後續節點(如 LINE 通知)使用的 JSON 物件。
  • LINE Bot 通知Updata (HTTP Request)
    • 功能與設定:也完全比照建立流程的設定。您可以稍微修改訊息內容,讓使用者知道這是「更新」通知。例如,在 Body 中可以這樣寫:

      {
        "messages": [
          {
            "type": "text",
            "text": "【活動更新通知🔔】\n{{$node["AI Agent Prompt for UPDATE"].json.output.properties.tool_result.description}}"
          }
        ]
      }
      

刪除活動流程

這個流程的目標是:當 Google 日曆中的活動被取消刪除時,自動在 Notion 中找到對應的頁面,並將其狀態標記為「已取消」,而不是真的從資料庫中刪除這筆紀錄。

節點設定:GCal Delete Trigger (Google Calendar Trigger)

  • 功能:這是刪除流程的起點。它會監控指定的 Google 日曆,一旦有活動被取消,就會觸發。
  • 如何設定
    1. 這部分的設定與「建立活動流程設定指引」中的 GCal Create Trigger 幾乎完全相同。
    2. 唯一的關鍵差別是,在 Trigger On 這個選項,您必須將其設定為 Event Cancelled (活動取消時觸發)。
  • 為何這樣設定:我們為「刪除/取消」這個特定事件建立一個專屬的自動化路徑。將觸發條件設為 Event Cancelled 可以確保只有在日曆活動被刪除時,此流程才會啟動。

節點設定:AI Agent Prompt for DELETE/CANCEL (LangChain Agent)

  • 功能:這是刪除流程的「大腦」。它的任務非常明確:根據被刪除的日曆活動 ID,在 Notion 中找到對應頁面,並將其狀態改為「已取消」。
  • 如何設定
    1. 新增一個 AI Agent 節點,並將 GCal Delete Trigger 連接到它的輸入端。

    2. Prompt: 在 Text 欄位中,貼上以下專為「刪除/取消」設計的指令。這段 Prompt 清晰地定義了兩步驟任務:

      你是專責處理「已刪除或取消 Google Calendar 事件」並在 Notion 中標記對應狀態的 AI 助理。
      
      ## 核心任務 (兩步驟)
      你的任務分為兩步,請依序執行:
      
      **第一步:尋找頁面**
      1.  使用 `Search Tool for Delete` 工具。
      2.  設定篩選條件,在 Notion 資料庫中尋找"GCal_Event_ID"屬性的值 **完全等於** 輸入事件資料中的 `id` 的頁面。
      
      **第二步:更新頁面狀態**
      1.  從第一步的搜尋結果中,取得 Notion 頁面的 `page_id`。
      2.  使用 `Update Tool for Delete` 工具來更新這個 `page_id` 對應的頁面。
      3.  **你只需要更新一個欄位**:將「狀態 (Status)」屬性的值,固定修改為「**已取消**」。
      4.  同時,將「Last Edited By」屬性更新為「Google Calendar」。
      
      ## 輸入的事件資料
      {{ JSON.stringify($json) }}
      
      ## 執行指示
      請立即根據上述兩步驟任務,先搜尋,再將對應的 Notion 頁面狀態更新為「已取消」。
      
    3. 同樣地,您需要為這個 Agent 連接 語言模型 (Language Model)工具 (Tools) 和 輸出解析器 (Output Parser)

  • 為何這樣設定:這個 Prompt 的指令非常精確。它告訴 AI 不要真的「刪除」Notion 頁面(這通常是個危險操作),而是去「更新」它的狀態欄位。這是一種更安全、更推薦的資料管理方式,保留了歷史紀錄以供未來查核。這再次凸顯了我們在建立流程中回寫 GCal_Event_ID 的重要性。

AI Agent 的工具箱 (Tools) for Delete

這個流程的工具箱與更新流程的配置完全相同。

1. Search Tool for Delete (Notion Tool) & 2. Update Tool for Delete (Notion Tool)

  • 功能與設定
    • 這兩個工具的設定方法與「更新活動流程」中的 Search Tool 和 Update Tool 完全一樣
    • 您需要新增兩個 Notion 節點,都設定為 Tool 模式。
    • 一個的 Operation 設為 Search
    • 另一個的 Operation 設為 Update
    • 最後,將這兩個節點的菱形輸出端,都連接到 AI Agent Prompt for DELETE/CANCEL 節點的 Tool 輸入端。
  • 為何這樣設定:我們為 AI 提供了它完成任務所需的「搜尋」和「更新」能力。AI Agent 會根據 Prompt 的指令,智能地先呼叫 Search Tool,用 GCal_Event_ID 找到目標,然後再呼叫 Update Tool,將該目標頁面的「狀態」欄位改成「已取消」。

節點設定:Update a Last Edited (Notion Node)

  • 功能:這個節點在您的 JSON 流程中扮演了一個輔助日誌記錄的角色。在 AI Agent 已經透過工具完成主要的「狀態更新」任務後,這個節點可以被用來執行一些額外的、固定的更新操作。
  • 如何設定
    1. 新增一個普通的 Notion 節點 (不是 Tool 模式)。
    2. 將 AI Agent Prompt for DELETE/CANCEL 的輸出連接到此節點的輸入。
    3. Operation: 選擇 Update。
    4. Page ID: 使用表達式填入 {{ $json.output.properties.tool_result.Notion_Event_ID }},從 AI 的輸出中獲取 Page ID。
    5. Properties: 根據您的 JSON 檔案,這裡可以留空或用來更新一些如「最後編輯時間」之類的元數據。AI Agent 本身已經處理了最重要的狀態變更。
  • 為何這樣設定:雖然 AI Agent 已經完成了核心任務,但有時我們希望在流程的最後再執行一個標準化的更新,例如記錄是哪個 n8n 流程最後動了這筆資料。這個節點提供了這樣的彈性。不過,對於這個「刪除」流程來說,最重要的工作(改狀態)已經由 AI Agent 在前一步完成了。

節點設定:Structured Output Parser2 & LINE Bot Delete 通知

這兩個部分的概念與前兩個流程完全相同。

  • Structured Output Parser2

    • 功能與設定:完全比照「建立活動流程設定指引」的設定。確保 AI 的最終回覆是我們能夠穩定解析的 JSON 格式。
  • 📱 LINE Bot Delete 通知 (HTTP Request)

    • 功能與設定:完全比照之前的設定。您可以自訂通知訊息,清楚地告知使用者有活動已被取消。
    {
      "messages": [
        {
          "type": "text",
          "text": "【活動取消通知🗑️】\n{{$node["AI Agent Prompt for DELETE/CANCEL"].json.output.properties.tool_result.description}}"
        }
      ]
    }`
    

    image

結語:

歷經三十天的技術長征,我們在 IT 鐵人賽的最終章,終於為 Notion 與 Google Calendar 的雙向同步拼上了最後一塊,也是至關重要的一塊拼圖。今天,我們成功地建構了從 Google Calendar 到 Notion 的單向同步工作流,並為「創建 (Create)」、「更新 (Update)」與「取消 (Cancelled)」事件分別設計了獨立且穩健的處理路徑。
值得一提的是,在處理「取消」事件時,我們選擇了將 Notion 頁面狀態更新為「已取消」,而非直接刪除。這不僅是一種務實且安全的技術權衡,更體現了在真實世界的自動化流程中,保留操作紀錄與數據完整性的重要性。同時,透過在 Notion 中加入 Last Edited By 屬性作為「守門員」,我們巧妙地解決了雙向同步中最棘手的「無限迴圈」問題,為整個系統的穩定性提供了堅實的保障。

在這30天的長途旅程我們學習中我們學會了使用 Claude desktop 串接 Notion,後面學習了如何使用n8n同步Notion資料庫。

雖說這好像不是奪大的成就,但我們也是開始了,慢慢來比較快。謝謝收看。


上一篇
Day 29 | Notion to Calendar 單向 CUD - 最終完善
系列文
生成式AI 與 Notion 的碰撞 ?! 你還在 ctrl+c ctrl+v ?30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
justin_log
iT邦新手 5 級 ‧ 2025-10-14 14:18:16

感謝 eating11111 的精彩分享!

AI 相關的技術分享總是令人興奮,期待更多深入的內容。

遇到的問題和解決方案分享很實用,相信很多人都會遇到類似的情況。

也歡迎版主有空參考我的系列文「iOS? AI-Yes!:用 Vide Coding 加速我的 Swift 學習曲線」:https://ithelp.ithome.com.tw/users/20178130/ironman/8677

如果覺得有幫助的話,也歡迎訂閱支持!

我要留言

立即登入留言